﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TasksUI.Controls
{
    public partial class TaskControl : UserControl
    {
        static TaskControl()
        {
            _pc[TasksModel.PriorityClass.High] = "High";
            _pc[TasksModel.PriorityClass.Low] = "Low";
            _pc[TasksModel.PriorityClass.Medium] = "Medium";
        }

        public TaskControl()
        {
            InitializeComponent();
            base.Disposed += new EventHandler(TaskControl_Disposed);
        }

        private void TaskControl_Disposed(object sender, EventArgs e)
        {
            if (_task != null)
                _task.PropertyChanged -= new PropertyChangedEventHandler(_task_PropertyChanged);
        }

        private TaskListControl _taskList;

        [DefaultValue(null)]
        public TaskListControl TaskList
        {
            [System.Diagnostics.DebuggerStepThrough]
            get { return _taskList; }
            [System.Diagnostics.DebuggerStepThrough]
            set { _taskList = value; }
        }

        private TasksModel.Task _task;

        [DefaultValue(null)]
        public TasksModel.Task Task
        {
            [System.Diagnostics.DebuggerStepThrough]
            get { return _task; }
            set
            {
                if (value == null)
                    return;
                if (!object.ReferenceEquals(_task, value))
                {
                    if (_task != null)
                        _task.PropertyChanged -= new PropertyChangedEventHandler(_task_PropertyChanged);
                    _task = value;
                    _task.PropertyChanged += new PropertyChangedEventHandler(_task_PropertyChanged);
                    RefreshView();
                }
            }
        }

        [DefaultValue(false)]
        public bool ReadOnly
        {
            [System.Diagnostics.DebuggerStepThrough]
            get { return !tbName.Enabled; }
            set
            {
                tbName.Enabled = !value;
                tmArchive.Visible = !value;
                tmMoveToTop.Visible = !value;
                tmMoveFromArchive.Visible = value;
            }
        }

        private void _task_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != "Order" && e.PropertyName != "ChangedAt")
                RefreshView();
        }

        private void RefreshView()
        {
            if (Tag != null)
                return;// sentinel
            tbName.Text = _task.Name;
            lInfo1.Text = _pc[_task.Priority];
            if (!string.IsNullOrEmpty(_task.Url))
            {
                lInfo3.Cursor = Cursors.Hand;
                lInfo3.Font = new System.Drawing.Font(lInfo3.Font, FontStyle.Underline);
                lInfo3.ForeColor = Color.Blue;
                lInfo3.Text = _task.Url.Replace("http://", string.Empty).
                    Replace("https://", string.Empty).Replace("mailto:", string.Empty);
            }
            else
            {
                lInfo3.Cursor = Cursors.Default;
                lInfo3.Font = new System.Drawing.Font(lInfo3.Font, FontStyle.Regular);
                lInfo3.ForeColor = SystemColors.ControlText;
                if (_task.Status != null && !string.IsNullOrEmpty(_task.Status.Description))
                    lInfo3.Text = _task.Status.Description;
                else
                    lInfo3.Text = "Created: " + _task.CreatedAt.ToString("HH:mm dd-MM-yyyy");
            }
            string label = string.Empty;
            label = Concat(label, AddDue());
            label = Concat(label, AddDone());
            if (label.Length < 20)
                label = Concat(label, AddEstimated(label.Length > 0));
            if (label.Length < 20)
                label=Concat(label, AddLocation(label.Length > 0));
            lInfo2.Text = label;
        }

        private string Concat(string a, string b)
        {
            if (a.Length == 0)
                return b;
            if (b.Length > 0)
                return a + " " + b;
            return a;
        }

        private string AddLocation(bool @long)
        {
            if (string.IsNullOrEmpty(_task.Location))
                return string.Empty;
            return (@long ? "Location: " : "Loc: ") + _task.Location;
        }

        private string AddEstimated(bool @long)
        {
            if (_task.EstimatedEffort <= 0)
                return string.Empty;
            return (@long ? "Estimated: " : "Est: ") + _task.EstimatedEffort + "h";
        }

        private string AddDue()
        {
            if (!_task.DueDate.HasValue)
                return string.Empty;
            bool @long = _task.DueDate.Value.Year != _year;
            return "Due: " + _task.DueDate.Value.ToString(@long ? "dd-MM-yyyy" : "dd-MM");
        }
        
        private string AddDone()
        {
            if (_task.Progress <= 0)
                return string.Empty;
            return "Done: " + _task.Progress + "%";
        }

        private static readonly int _year = DateTime.Now.Year;

        private readonly static Dictionary<TasksModel.PriorityClass, string> _pc =
            new Dictionary<TasksModel.PriorityClass, string>(4);

        private void tbName_TextChanged(object sender, EventArgs e)
        {
            if (Tag != null) 
                return;
            Tag = this;
            try
            {
                _task.Name = tbName.Text;
                _task.ChangedAt = DateTime.UtcNow;
            }
            finally
            {
                Tag = null;
            }
        }

        private void TaskControl_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                if (e.Clicks == 1)
                    _taskList.BeginDrag(this);
                else
                    if (e.Clicks == 2)
                    {
                        if (sender == lInfo3)
                            lInfo3_DoubleClick(sender, e);
                        else
                            TaskControl_DoubleClick(sender, e);
                    }
        }

        private void tmRemove_Click(object sender, EventArgs e)
        {
            TaskList.Remove(this);
        }

        private void tmCompleted_Click(object sender, EventArgs e)
        {
            _task.MarkCompleted();
        }

        private void tmArchive_Click(object sender, EventArgs e)
        {
            Main main = (Main)TopLevelControl;
            TaskList.Remove(this);
            main.Archive(_task);
        }

        private void TaskControl_DoubleClick(object sender, EventArgs e)
        {
            Main main;
            if (TopLevelControl is Main)
                main = (Main)TopLevelControl;
            else
                if (((Form)TopLevelControl).Owner is Main)
                    main = (Main)((Form)TopLevelControl).Owner;
                else
                    main = (Main)(((Form)TopLevelControl).Owner).Owner;
            if (ReadOnly)
                main.ViewTask(Task);
            else
                main.EditTask(Task);
        }

        private void tmMoveFromArchive_Click(object sender, EventArgs e)
        {
            Main main = (Main)((TaskArchive)TopLevelControl).Owner;
            TaskList.Remove(this);
            main.FromArchive(_task);
        }

        private void tmMoveToTop_Click(object sender, EventArgs e)
        {
            Main main = (Main)TopLevelControl;
            TaskList.MoveToTop(this);
        }

        private void lInfo3_DoubleClick(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(_task.Url))
            {
                System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(
                    _task.Url.Trim());
                psi.UseShellExecute = true;
                System.Diagnostics.Process.Start(psi);
                return;
            }
            TaskControl_DoubleClick(null, null);
        }
    }
}